import { provide, reactive, computed, defineComponent, Teleport } from "vue";
import Button from "../button";
import Header from "./Header";
import Body, { baseProps } from "./Body";
import { CALENDAR_KEY } from "./day";
import { copyDates } from "./useCalendar";
import { createNamespace, extend } from "../utils";
const [name, bem] = createNamespace("calendar");

export default defineComponent({
  name,
  props: extend({}, baseProps, {
    // 是否可见
    visible: Boolean,
    // 默认选中日期(不需要传时间，内部用毫秒对比，每天的0时0分0秒0毫秒开始)
    defaultDate: {
      type: [Date, Array],
      default() {
        const now = new Date();
        return new Date(now.getFullYear(), now.getMonth(), now.getDate());
      },
    },
    // 底部文字配置
    bottomFormatter: Function,
    // 是否允许日期范围的起止时间为同一天
    allowSameDay: Boolean,
    // 区间选中超过最大值触发,默认用alert提示外部可以结合其他ui库提示
    rangePrompt: {
      type: Function,
    },
    // 底部按钮文字
    confirmText: {
      type: String,
      default: "确定",
    },
    // 底部按钮禁用文字
    confirmDisabledText: {
      type: String,
      default: "确定",
    },
  }),

  emits: ["confirm", "update:visible"],

  setup(props, { slots, emit }) {
    // 获取初始日期
    const getInitialDate = (): any => {
      // 不是单选又不是数组就用数组包装起来
      return props.type !== "single" && !Array.isArray(props.defaultDate) ? (props.defaultDate ? [props.defaultDate] : []) : props.defaultDate;
    };

    const state = reactive({
      selectedDate: getInitialDate(),
    });

    // 计算按钮禁用状态
    const isDisable = computed(() => {
      if (!state.selectedDate || (props.type === "multiple" && !state.selectedDate.length) || (props.type === "range" && state.selectedDate.length < 2)) {
        return true;
      }
      return false;
    });

    // 处理日期选择
    const handlerSelect = (date: Date) => {
      // 单选
      if (props.type === "single") {
        state.selectedDate = date;
      } else if (props.type === "multiple") {
        // 多选
        if (state.selectedDate.some((item: Date) => item.getTime() === date.getTime())) {
          // 存在就过滤掉
          state.selectedDate = state.selectedDate.filter((item: Date) => item.getTime() !== date.getTime());
        } else {
          // 不存在就加入进去
          state.selectedDate.push(date);
        }
      } else if (props.type === "range") {
        // 区间选择
        let range = state.selectedDate.slice();
        if (range.length === 1) {
          // 第二个小于第一个直接删掉第一个, 不允许同一天也会删除第一个
          if (date.getTime() < range[0].getTime() || (!props.allowSameDay && date.getTime() === range[0].getTime())) {
            range.shift();
          } else {
            let timeStampRange = date.getTime() - range[0].getTime();
            let timeStampDay = 1000 * 60 * 60 * 24;
            if (props.maxRange != 0 && timeStampRange / timeStampDay > props.maxRange) {
              // 由外部去提示自由度会高很多
              props.rangePrompt && props.rangePrompt(props.maxRange);
              // 结束日期设置成最大允许日期
              date = new Date(range[0].getTime() + timeStampDay * props.maxRange);
            }
          }
        } else if (range.length > 1) {
          // 已经有两个值直接清空数组
          range.length = 0;
        }

        range.push(date);
        state.selectedDate = range;
      }
    };

    // 回到默认值(外部获取实例调用)
    const reset = () => {
      state.selectedDate = getInitialDate();
    };

    // 关闭日历
    const handlerClose = () => {
      emit("update:visible", false);
    };

    // 确定提交数据
    const handlerConfirm = () => {
      // 拷贝一份普通数据给外部使用防止外部修改
      emit("confirm", copyDates(state.selectedDate));
      handlerClose();
    };

    // 提供给子组件使用
    provide(CALENDAR_KEY, {
      handlerSelect,
      bottomFormatter: props.bottomFormatter,
    });

    return () => {
      const { visible, confirmDisabledText, confirmText, type, minDate, maxDate, maxRange } = props;

      return (
        <Teleport to="body">
          <div class={[bem(), { "is-show": visible }]}>
            <Header onBack={handlerClose} />
            <Body type={type} minDate={minDate} maxDate={maxDate} selectedDate={state.selectedDate} maxRange={maxRange} />
            <div class={bem("footer")}>
              <Button size="small" type="primary" round block disabled={isDisable.value} onClick={handlerConfirm}>
                {isDisable.value ? confirmDisabledText : confirmText}
              </Button>
            </div>
          </div>
        </Teleport>
      );
    };
  },
});
